--[[

  Copyright (c) 2012-2013 Baby-Bus.com 
  http://www.babybus.com/ 

]] 




--[[
    工具类
--]]
local M = {}


--[[--
检测两个结点是否有碰撞(修改框架的检测，可以有x，y方向大小控制)
### Useage:
### Aliases:
### Notice:
    参数集合说明:
    [必填项]
        CCNode      **node1**           结点1
        CCNode      **node2**           结点2
    [关键项] 
        number        **factorNode1X**     结点1区域X缩放系数(默认为1.0)
        number        **factorNode2X**     结点2区域X缩放系数(默认为1.0)
        number        **factorNode1Y**     结点1区域Y缩放系数(默认为1.0)
        number        **factorNode2Y**     结点2区域Y缩放系数(默认为1.0)
    [选填项]

    [其他项]
### Parameters:
-   table **params**        参数集合
### Returns:
-   bool                    是否产生碰撞的布尔值
--]]
function M:detectCollision(params)
    -- 参数赋值
    local node1            = params.node1
    local node2            = params.node2
    local factorNode1    = params.factorNode1
    local factorNode2    = params.factorNode2
    local factorNode1X    = ifnil(params.factorNode1X, 1)
    local factorNode2X    = ifnil(params.factorNode2X, 1)
    local factorNode1Y    = ifnil(params.factorNode1Y, 1)
    local factorNode2Y    = ifnil(params.factorNode2Y, 1)

    if factorNode1 then
        factorNode1X = factorNode1
        factorNode1Y = factorNode1
    end
    if factorNode2 then
        factorNode2X = factorNode2
        factorNode2Y = factorNode2
    end


    -- local box1 = node1:getContentSize()
    -- local box2 = node2:getContentSize()

    local box1 = node1:getBoundingBox()
    local box2 = node2:getBoundingBox()

    local width, height, x, y
    -- x = node1:point().x - box1.width * node1:anchor().x * node1:scaleX()
    -- y = node1:point().y - box1.height * node1:anchor().y * node1:scaleY()
    x    = box1.x
    y    = box1.y
    width = box1.width * node1:scaleX()
    height = box1.height * node1:scaleY()
    box1 = cc.rect(
      x + width * (1 - factorNode1X) * 0.5,
      y + height * (1 - factorNode1Y) * 0.5,
      width * factorNode1X,
      height * factorNode1Y
    )

    -- x = node2:point().x - box2.width * node2:anchor().x * node2:scaleX()
    -- y = node2:point().y - box2.height * node2:anchor().y * node2:scaleY()
    x    = box2.x
    y    = box2.y
    width = box2.width * node2:scaleX()
    height = box2.height * node2:scaleY()
    box2 = cc.rect(
      x + width * (1 - factorNode2X) * 0.5,
      y + height * (1 - factorNode2Y) * 0.5,
      width * factorNode2X,
      height * factorNode2Y
    )

    local point

    point = node1:getParent():convertToWorldSpace(cc.p(box1.x, box1.y))
    box1 = CCRect(point.x, point.y, box1.width, box1.height)

    point = node2:getParent():convertToWorldSpace(cc.p(box2.x, box2.y))
    box2 = CCRect(point.x, point.y, box2.width, box2.height)
    return cc.rectIntersectsRect(box1, box2)
end

-- 切换父节点
function M:changeParent(node, newParent, zOrder)
    local z = ifnil(zOrder, node:getZOrder())
    node:retain()
    node:removeFromParent()
    node:to(newParent, z)
    node:release()
end

-- 辅助节点
function M:loadHelpRect(node, x, y, width, height, znum, anchorPoint)
    if not znum then znum = 500 end
    local anchor = ifnil(anchorPoint, cc.p(0.5, 0.5))
    local a = U.loadSprite({
        imgName    = "blank.png",
        scale9    = true,    
        contentSize = CCSize(width, height),
        color    = ccc3(0, 0, 0),
    }):opacity(100):to(node, znum):anchor(anchor):p(x, y)--:bindTouchLocate()
    return  a
end

--[[--
切屏效果：裁切退出

### Useage:

### Aliases:

### Notice:

### Example:

### Parameters:
-   CCNode              **node**               			[必选] 挂载的结点
-   string              **imgpath**            			[必选] 裁切的图片
-   layer               **originLayer**                 [可选] 原图层
-   nim                **isChangeScene**  	   			[必选] 是否需要切换场景(true: 切换场景，false：加载图层)
-   string              **sceneOrLayerName**            [必选] 场景名
--  params              ** tabele***                    [可选] 参数   
-   endScaleNum                                         [可选] 缩放后的最终大小（默认0）
### OptionParameters

### Returns: 
-   nil   

--]]
--                        node,  "", _, true, 
function M:exitSceneScale(node, imgPath, originLayer, isChangeScene, sceneOrLayerName, params, pos, endScaleNum)
    local pos = pos or cc.p(480 + X_OFFSET, 270 * Y_FACTOR)
    local endScaleNum = ifnil(endScaleNum, 0)
    node.mask = U.loadLayer({ color = ccc4(0, 0, 0, 255) })
    -- 模板
    node.templet = D.img(imgPath):p(480 + X_OFFSET, 270 * Y_FACTOR)
    node.templet:scale(10)
    local m_clip = CCClippingNode:create()
    --或直接在create(self.templet)传入
    m_clip:setStencil(node.templet)
    --设置遮罩模式[true：显示模板区域，false：显示模板外区域]
    m_clip:setInverted(true)
    --设置ALPHA的测试参考值    
    m_clip:setAlphaThreshold(0)

    node:addChild(m_clip, 10000000)
    m_clip:addChild(node.mask, 10000000)

    node.templet:line({
        A.union({
            { "scaleTo", 1, endScaleNum},
            { "moveto", 1, pos}
            }),
        { "delay", 0.2 },
        { "fn", function()
            if isChangeScene then
                game:enterScene(sceneOrLayerName, params)
            else
                -- 移除原来的图层
                originLayer:remove()
                -- 在加载新的图层
                D.getRunningScene():loadLayer(sceneOrLayerName)
            end
        end },
    })
end

--[[--

切屏效果：裁切进入
### Parameters:
-   CCNode              **node**               [必选] 挂载的结点
-   string              **imgpath**            [必选] 裁切的图片
-   function            **cb**                 [可选] 回调函数
### OptionParameters

### Returns: 
-   nil   
--]]
--
function M:enterSceneScale(node, imgPath, cb)
    node.mask = U.loadLayer({ color = ccc4(0, 0, 0, 255) })
    -- 模板
    node.templet = D.img(imgPath):p(480 + X_OFFSET, 270 * Y_FACTOR)
    node.templet:scale(0)
    local m_clip = CCClippingNode:create()
    --或直接在create(self.templet)传入
    m_clip:setStencil(node.templet)
    --设置遮罩模式[true：显示模板区域，false：显示模板外区域]
    m_clip:setInverted(true)
    --设置ALPHA的测试参考值    
    m_clip:setAlphaThreshold(0)

    node:addChild(m_clip, 1000)
    m_clip:addChild(node.mask, 1000)

    CCNodeExtend.extend(m_clip)
    node.templet:line({
        { "scaleTo", 1, 10 },
        { "fn", function()
            m_clip:remove()
            m_clip = nil
            if cb and type(cb) == "function" then
                cb()
            end
        end },
        { "remove" }
    })
end


function M:bindTouchLocate(node, handler)
    -- [参数构建]
    local params    = {}
    params.pnHandle = true
    params.fnHandle = handler
    params.fnBegan  = function(sender, x, y, touches) 
        node.lBeganPos_   = node:point()
        node.lBeganPoint_ = ccp(x, y)
        return true 
    end
    params.fnMoved  = function(sender, x, y, touches)
        node:p(ccpAdd(node.lBeganPos_, ccpSub(ccp(x, y), node.lBeganPoint_)))
    end
    params.fnEnded  = function(sender, x, y, touches)
    end

    -- [事件绑定]
    node:bindTouch(params)

    return node
end


-- 小屏去广告
function M:isLoadAd()  
    local bRet = false
    
    if isandroid() and (Y_FACTOR - 1.185) > 0.00000001 then
        bRet = true
    end
    
    if isiphone() then
       bRet = false
    elseif isipad() then
       bRet = true
    end

    if not bRet then
        NV.removeAd()
    end
    return bRet
end



-- 输出精灵表中所有精灵的坐标或某项信息
-- nodeTable 精灵表
-- isWorld   输出世界坐标
-- colMax    最大列数
-- fun       自定义的返回精灵数据的函数
-- isXoffset  是否添加X偏移值
-- isYoffset  是否添加Y偏移值
function M:printNodeTable(nodeTable, isWorld, colMax, func, isXoffset, isYoffset)
    if not nodeTable then print("no table") return end
    isWorld     = ifnil(isWorld, false)
    colMax      = ifnil(colMax, 5)
    isXoffset   = ifnil(isXoffset, false)
    isYoffset   = ifnil(isYoffset, false)

    local Xoffset = isXoffset and " + X_OFFSET" or ""
    local Yoffset = isYoffset and " + NEW_Y_OFFSET" or ""

    local isPos = false     -- 是否是坐标
    -- 如果没有自定义返回数据的函数
    if not func then
        isPos = true
        if isWorld then
            func = function (node)
                return node:worldpoint()
            end
        else
            func = function (node)
                return node:point()
            end
        end
    end
    -- 开头
    local str = "\n{\n\t"
    for k,v in pairs(nodeTable) do
        local data = func(v)
        -- 换行
        if (k-1) % colMax == 0 and k~=1 then
            str = str.."\n\t"
        end

        local s
        -- 如果是坐标
        if isPos then
            s = string.format("cc.p(%d%s, %d%s), ", data.x, Xoffset, data.y, Yoffset)
            str = str..s
        else
            str = str..string.format("%d, ", data)
        end
    end
    -- 结尾
    str = str.."\n}"
    print(str)
end

-- 根据键值获取table的值
function M:getValueWithKey(table, key)
    local result = nil
    for k, v in pairs(table) do
        if k == key then
            result = v
            break
        end
    end
    return result
end

-- 从table中随即获取一个item，去重(子项为cc.p的无效）
-- param： table table 目标表
-- param： oldItem 要去重的项
function M:getItemForTableExcept(desTable, oldItem)
    T.shuffle(desTable, #desTable)
    local newItem = T.random(desTable)
    if oldItem and type(oldItem) == "table" and T.count(desTable) > 1 then
        for k, v in pairs(oldItem) do
            if newItem == v then
                return self:getItemForTableExcept(desTable, oldItem)
            end
        end
    else
        if oldItem then
            if oldItem == newItem and T.count(desTable) > 1 then
                return self:getItemForTableExcept(desTable, oldItem)
            end
        end
    end

    return newItem
end

function M:isTouchInside(node, x, y, isCascade, isConvertToWorld, factorX, factory)
    -- [操作参数]
    -- 触控点
    local point     = ccp(x, y)
    -- 区域系数x
    local factorX   = ifnil(factorX, 1.0)
    -- 区域系数y
    local factorY   = ifnil(factory, 1.0)
    -- 区域偏移x
    local offsetX   = 0
    -- 区域偏移y
    local offsetY   = 0

    -- [参数赋值]
    if node.existsProperty then 
        if node:existsProperty("rectFactorX") then 
            factorX = tonumber(node:getProperty("rectFactorX"))
        end
        if node:existsProperty("rectFactorY") then 
            factorY = tonumber(node:getProperty("rectFactorY"))
        end
        if node:existsProperty("rectOffsetX") then 
            offsetX = tonumber(node:getProperty("rectOffsetX"))
        end
        if node:existsProperty("rectOffsetY") then 
            offsetY = tonumber(node:getProperty("rectOffsetY"))
        end
    end 


    -- [触控判断]
    local box = ND.getBoundingBox({ 
        node                = node, 
        isCascade           = isCascade, 
        isConvertToWorld    = isConvertToWorld,
        factorX             = factorX,
        factorY             = factorY,
        offsetX             = offsetX,
        offsetY             = offsetY,
    })


    return cc.rectContainsPoint(box, point) or (box.width == 0 and box.height == 0)
end

---------------------
-- 自动化测试命名
---------------------
--[[--
    node:设置节点
    nodeName:节点名字
]]
function M:setNodeName(node, nodeName, scene)
    local sceneName = scene.name
	sceneName = string.lower(string.sub(sceneName, 1, string.len(sceneName) - 5))
    nodeName  = string.upper(string.sub(nodeName, 1, 1))..string.sub(nodeName, 2, string.len(nodeName))
    local name = sceneName..nodeName
	node:setName(name)
end

----------------------
-- 移除表中对应的值
----------------------
--[[--
    tables:操作表
    value:移除值
]]
function M:removeTableValue(tables, value)
    for i=#tables, 1, -1 do
        if tables[i] == value then
            table.remove(tables, i)
        end
    end
end


--[[--

停止指定对象的指定动作

### Useage:

### Aliases:

### Notice:
	说明

### Example:

### Parameters:
- 	CCNode 		**node** 				[必选] 要停止动作的节点对象
- 	CCAction 	**action** 				[必选] 要停止的动作对象

### OptionParameters

### Returns: 
-   nil 								返回空值，方便指针置空。

--]]--
function M:stopAction(node, action)
 	if node and action then 
 		node:stopAction(action)
 	end

 	return nil 
end 

-- 根据图片创建粒子
function M:creatrParticleWithImage(partcleFile, imgPath)
	local particle = P.newParticle(partcleFile)
	particle:setTexture(CCTextureCache:sharedTextureCache():addImage(imgPath))
	return  particle
end

-- 自动移除粒子（在粒子结束的时候自动移除）
-- param: particle cc.particle 要操作的粒子
function M:autoRemovParticle(particle)
    local duration = particle:getDuration()
    particle:line({
        {"delay", duration},
        {"fn", function()
            particle:stopSystem()
            particle:remove()
        end},
    })
    return nil
end

-- 切割数据，获取对应的行和列（翻书中，每一页贴纸的类型，坐标数据在由上到下，是右金字塔排列->>>Data.PasterPos，根据行列获取对应的坐标位置）
function M:getLineAndRow(img)
    local tab = S.split(img, "_", 2)
    -- 返回行列
    return tonumber(tab[1]), tonumber(tab[2])
end


return M






